<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import { fetchReportDetail, fetchChartData } from '@/service/api';
import * as echarts from 'echarts';

defineOptions({
  name: 'ReportPreviewModal'
});

interface Props {
  reportId?: number;
}

const props = defineProps<Props>();

const visible = defineModel<boolean>('visible', { required: true });

const loading = ref(false);
const report = ref<Api.DataPlatform.ReportDetail | null>(null);
const chartRefs = ref<Record<string, HTMLElement>>({});

// 加载报表详情
async function loadReport() {
  if (!props.reportId) return;

  loading.value = true;
  try {
    const { data } = await fetchReportDetail(props.reportId);
    if (data) {
      report.value = data;
      // 延迟渲染图表，确保DOM已挂载
      setTimeout(() => {
        renderCharts();
      }, 100);
    }
  } finally {
    loading.value = false;
  }
}

// 渲染图表
async function renderCharts() {
  if (!report.value?.chartConfig) return;

  try {
    const config = JSON.parse(report.value.chartConfig);
    const charts = config.charts || [];

    for (const chart of charts) {
      await renderChart(chart);
    }
  } catch (error) {
    console.error('渲染图表失败:', error);
    window.$message?.error('渲染图表失败');
  }
}

// 渲染单个图表
async function renderChart(chartConfig: any) {
  const chartId = chartConfig.id;
  const chartElement = chartRefs.value[chartId];

  if (!chartElement || !props.reportId) return;

  try {
    // 获取图表数据
    const { data } = await fetchChartData(props.reportId, chartId, {});

    if (!data) return;

    // 初始化ECharts实例
    const chartInstance = echarts.init(chartElement);

    // 根据图表类型构建配置
    const option = buildChartOption(chartConfig.type, data);

    // 渲染图表
    chartInstance.setOption(option);

    // 自动刷新
    if (report.value?.refreshInterval && report.value.refreshInterval > 0) {
      setInterval(() => {
        renderChart(chartConfig);
      }, report.value.refreshInterval * 1000);
    }
  } catch (error) {
    console.error(`渲染图表 ${chartId} 失败:`, error);
  }
}

// 构建图表配置
function buildChartOption(chartType: string, chartData: Api.DataPlatform.ChartData) {
  const data = chartData.data || [];

  switch (chartType) {
    case 'bar':
      return buildBarOption(data);
    case 'line':
      return buildLineOption(data);
    case 'pie':
      return buildPieOption(data);
    case 'gauge':
      return buildGaugeOption(data);
    default:
      return {};
  }
}

// 构建柱状图配置
function buildBarOption(data: any[]) {
  if (data.length === 0) return {};

  const keys = Object.keys(data[0]);
  const xAxisData = data.map(item => item[keys[0]]);
  const seriesData = data.map(item => item[keys[1]]);

  return {
    title: { text: '柱状图' },
    tooltip: {},
    xAxis: { type: 'category', data: xAxisData },
    yAxis: { type: 'value' },
    series: [{ type: 'bar', data: seriesData }]
  };
}

// 构建折线图配置
function buildLineOption(data: any[]) {
  if (data.length === 0) return {};

  const keys = Object.keys(data[0]);
  const xAxisData = data.map(item => item[keys[0]]);
  const seriesData = data.map(item => item[keys[1]]);

  return {
    title: { text: '折线图' },
    tooltip: {},
    xAxis: { type: 'category', data: xAxisData },
    yAxis: { type: 'value' },
    series: [{ type: 'line', data: seriesData }]
  };
}

// 构建饼图配置
function buildPieOption(data: any[]) {
  if (data.length === 0) return {};

  const keys = Object.keys(data[0]);
  const seriesData = data.map(item => ({
    name: item[keys[0]],
    value: item[keys[1]]
  }));

  return {
    title: { text: '饼图' },
    tooltip: {},
    series: [
      {
        type: 'pie',
        radius: '50%',
        data: seriesData
      }
    ]
  };
}

// 构建仪表盘配置
function buildGaugeOption(data: any[]) {
  if (data.length === 0) return {};

  const keys = Object.keys(data[0]);
  const value = data[0][keys[0]];

  return {
    title: { text: '仪表盘' },
    series: [
      {
        type: 'gauge',
        detail: { formatter: '{value}' },
        data: [{ value, name: '指标' }]
      }
    ]
  };
}

// 设置图表引用
function setChartRef(chartId: string, el: HTMLElement | null) {
  if (el) {
    chartRefs.value[chartId] = el;
  }
}

// 监听模态框打开
watch(visible, val => {
  if (val) {
    loadReport();
  } else {
    report.value = null;
    chartRefs.value = {};
  }
});
</script>

<template>
  <NModal v-model:show="visible" preset="card" title="报表预览" style="width: 90%; max-width: 1400px">
    <NSpin :show="loading">
      <div v-if="report" class="report-preview">
        <div class="report-header mb-16px">
          <h2>{{ report.name }}</h2>
          <p class="text-gray-500">{{ report.description }}</p>
        </div>

        <div v-if="report.chartConfig" class="charts-container">
          <template v-if="JSON.parse(report.chartConfig).charts">
            <div
              v-for="chart in JSON.parse(report.chartConfig).charts"
              :key="chart.id"
              class="chart-item mb-16px"
              style="height: 400px"
            >
              <div :ref="el => setChartRef(chart.id, el as HTMLElement)" style="width: 100%; height: 100%" />
            </div>
          </template>
          <NEmpty v-else description="暂无图表配置" />
        </div>
        <NEmpty v-else description="暂无图表配置" />
      </div>
      <NEmpty v-else description="暂无数据" />
    </NSpin>
  </NModal>
</template>

<style scoped>
.report-preview {
  padding: 16px;
}

.report-header h2 {
  margin: 0 0 8px 0;
  font-size: 24px;
  font-weight: 600;
}

.charts-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
  gap: 16px;
}

.chart-item {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 16px;
  background: #fff;
}
</style>
